<template>
  <div class="app-container">
    <el-card class="box-card">
      <categorySelector @changeCategory="changeCategory" :isShowList="isShowList"></categorySelector>
    </el-card>
    <el-card class="box-card" style="margin-top:20px">
      <div v-show="isShowList">
        <el-button type="primary" icon="el-icon-plus" @click="showAddDiv" :disabled="!category3Id">添加属性</el-button>
        <el-table :data="attrList" style="width:100%" >
          <el-table-column type="index" label="序号"  align="center" width="80"></el-table-column>
          <el-table-column prop="attrName" label="属性名称"></el-table-column>
          <el-table-column label="属性值列表">
            <template slot-scope="{row,$index}">
              <el-tag type="success" v-for="(attrVal,index) in row.attrValueList" :key="attrVal.id">{{attrVal.valueName}}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <template slot-scope="{row,$index}">
              <HintButton type="warning" icon="el-icon-edit" size="mini" @click="editAttr(row)" title="修改" ></HintButton>
              <el-popconfirm :title="`确定删除${row.attrName}吗`" @onConfirm="delAttr(row)">
                <HintButton type="danger" icon="el-icon-delete" size="mini" title="删除" slot="reference"></HintButton>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div v-show="!isShowList">
        <el-form :model="attrForm" :inline="true">
          <el-form-item label="属性名">
            <el-input palceholder="请输入属性名" v-model="attrForm.attrName"></el-input>
          </el-form-item>
         </el-form>
          <el-button type="primary" icon="el-icon-plus" :disabled="!attrForm.attrName" @click="addAttrValue">添加属性</el-button>
          <el-button @click="cancelAdd">取消</el-button>
          <p>
            <el-table border style="width:100%" :data="attrForm.attrValueList">
              <el-table-column type="index" label="序号" width="80"></el-table-column>
              <el-table-column label="属性值名称">
                <template slot-scope="{row,$index}">
                  <el-input placeholder="请输入属性值名称" 
                  size="mini" :ref="$index" 
                  v-model.trim="row.valueName" v-if="row.isEdit" @blur="toLook(row)" @keyup.enter.native="toLook(row)" ></el-input>
                  <span v-else @click="toEdit(row,$index)" style="display:block;height:100%">{{row.valueName}}</span>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="80">
                <template slot-scope="{row,$index}">
                  <el-popconfirm :title="`确定删除${row.valueName}吗`" @onConfirm="deleteAttrVal($index)">
                    <HintButton type="danger" title="删除" icon="el-icon-delete" size="mini" slot="reference"></HintButton>
                  </el-popconfirm>
                </template>
              </el-table-column>
            </el-table>
          </p>
          <p>
            <el-button type="primary" icon="el-icon-plus" @click="save" :disabled="attrForm.attrValueList.length===0">保存</el-button>
            <el-button @click="isShowList=true">取消</el-button>
          </p>
        
      </div>
    </el-card>
  </div>       
</template>

<script>
// 按需引入
import {cloneDeep} from  "lodash"
export default {
  name:"attr",
  components: {},
  data() {
    return {
      category1Id:"",
      category2Id:"",
      category3Id:"",
      attrList:[],
      isShowList:true,
      attrForm:{
        attrName:"",
        categoryId: 0,    // 不能写this.category3Id,  不能复用data中的数据，这里给一个初始值
        attrValueList:[], // 属性值列表
        categoryLevel:3
      },
    };
  },
  computed: {},
  methods: {
    changeCategory(categoryData){
      let {index,id} = categoryData
      if(index === 1) {
        this.category1Id = id;
        this.category2Id = "";
        this.category3Id = "";
        this.attrList = [];  //不清空的话下面的列表里还是会有数据。
      }
      if(index === 2) {
        this.category2Id = id;
        this.category3Id = "";
        this.attrList = []
      }

      if(index === 3){
        this.category3Id = id;
        // console.log( this.category1Id,this.category2Id,this.category3Id)
        this.getAttrInfoList(this.category1Id,this.category2Id,this.category3Id)
      }
    },

    async getAttrInfoList(category1Id,category2Id,category3Id){
      const {code,data} = await this.$api.attr.getAttrInfoList(category1Id,category2Id,category3Id)
      if(code === 200){
        this.attrList = data
      }
    },
    showAddDiv(){
      // 清空上一次添加 v-model 绑定的数据,恢复初始状态并迭代 categoryId
      // 手动重置，不可以用浅克隆 Object.assign(this,attrForm,this.$options.data.attrForm)
      this.attrForm ={
        attrName:"",
        categoryId: this.category3Id,    
        attrValueList:[], 
        categoryLevel:3
      }

    
      this.isShowList = false
    },
    cancelAdd(){
      this.isShowList = true
    },
    addAttrValue(){
      // 点击时 界面出现一行输入框 即对应的valueList 中加一个元素，
      this.attrForm.attrValueList.push({
        attrId:this.attrForm.id, // 新增时没有，获取来编辑的时候有。
        valueName:"",
        isEdit:true,
      })

      // 新增加的最后一个input 自动获取焦点。获取最新的input
      // attrValueList数据添加很快，但是真实的 DOM 还没有渲染出来，所以此处无法直接在当前渲染中获取dom
      // console.log(this.$refs[this.attrForm.attrValueList.length-1])
      this.$nextTick(()=>{
        this.$refs[this.attrForm.attrValueList.length-1].focus();
      })

    },
    editAttr(row){
      // console.log(row);
      this.isShowList = false;
      // this.attrForm = {...row} 
      // row是attrList 下的每一个form，
      // 但是浅拷贝不可行，拷贝的是地址，修改界面的数据会影响原本里的form，改变了已经请求回来的数据，界面一刷新就失效了。
      // 我们希望拷贝的只是值，与原先的对象没有关系。这样我们提交保存，发送请求完成修改。 
      this.attrForm = cloneDeep(row)
      this.attrForm.attrValueList.forEach((attr)=>{
        // 修改输入框效果的设置。选中状态为input，非选中状态为input
        // attr.isEdit = fasle; 对象设置属性不能直接这样设置。
        this.$set(attr,"isEdit",false)    
      })
    },

    // 编辑模式和查看模式
    toEdit(row,$index){
      // 改变为编辑模式
      row.isEdit = true;
    
      // 控制点击的input 自动聚焦
      // 这里因为点击时还是span 标签，渲染成input需要时间。因此通过refs获取dom input 也是需要在input渲染之后。故动用nextTick
      this.$nextTick(()=>{
        this.$refs[$index].focus()
      })
      
      // this.$refs[$index].focus();
    },
    toLook(row){
      // span 标签内必须有内容才能触发click 事件，所以 保证添加的属性不能为空
      let valueName = row.valueName; // 去空格放上面做了
      if(valueName === ""){
        this.$message.error("属性值不能为空")
        // row.valueName =""   // 这一步是否有必要
        return
      }
      
      // 属性值也不能重复 , 用 some不是every
      let isRepeat = this.attrForm.attrValueList.some((attrVal)=>{
        if(attrVal !== row){
          return attrVal.valueName === valueName
        }
      })
      if(isRepeat){
        this.$message("属性值名称不能重复")
        row.valueName = "" ;
        return
      };
      row.isEdit = false;
    },
    // 删除 attrVal值
    deleteAttrVal($index){
      this.attrForm.attrValueList.splice($index,1)
    },

    // 删除属性并发送请求
    async delAttr(row){
      //删除的接口中只需要id值，而row中就有，所以传row
    try{
      const {code} = await this.$api.attr.deleteAttr(row.id)
      if(code === 200){
        this.$message.success("删除成功")
        this.getAttrInfoList(this.category1Id,this.category2Id,this.category3Id)
      }
    }catch(e){
      this.$message.error("删除失败")
    }
      
    },

    // 保存修改或新增
    async save(){
      // 此处的attrForm 是有多余数据的：isEdit 
      let attrForm = this.attrForm

      // attrForm 的 valueList 中排除空字符串的属性值。
      let attrValueList = attrForm.attrValueList.filter((item,index)=>{
        if(item.valueName !== "" ){
          delete item.isEdit; 
          return true   // 不是return item
        };
      })
      attrForm.attrValueList = attrValueList

      // 属性列表为空，没有属性值，则不能继续
      if(attrValueList.length === 0){
        return
      }

      try{
        const result = await this.$api.attr.addOrUpdateAttr(attrForm)
        if(result.code === 200){
          this.$message.success("保存成功")
        }
        this.isShowList = true 
        // 重新获取数据列表
        this.getAttrInfoList(this.category1Id,this.category2Id,this.category3Id)

      }catch(e){
        this.$message.error("保存失败")
      }
    }
  },
 

  mounted(){}
};
</script>
<style scoped>
</style>